package com.example.onlinemonitoring.Util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Pattern;

import org.apache.ibatis.jdbc.Null;

public class HexUtil {

    /**
     * 16进制数字字符集
     */
    private static String hexString = "0123456789ABCDEF";

    /**
     * 将16进制数字解码成字符串,适用于所有字符（包括中文）
     */
    public static String HexStringToString(String bytes) throws UnsupportedEncodingException {
        bytes = bytes.replace(" ", "");
        ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length() / 2);
        // 将每2位16进制整数组装成一个字节
        for (int i = 0; i < bytes.length(); i += 2)
            baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString.indexOf(bytes.charAt(i + 1))));
        return new String(baos.toByteArray(), "GBK");
    }

    public static String string2Unicode(String string) {
        StringBuffer unicode = new StringBuffer();
        for (int i = 0; i < string.length(); i++) {
            // 取出每一个字符
            char c = string.charAt(i);
            unicode.append(Integer.toHexString(c) + " ");
        }

        return unicode.toString();
    }

    public static String unicode2String(String unicode) { // unicode转字符串
        if (unicode != null && !"".equals(unicode)) {
            StringBuffer string = new StringBuffer();
            String[] hex = unicode.split(" ");
            for (int i = 0; i < hex.length; i++) {
                int data = Integer.parseInt(hex[i], 16);
                string.append((char) data);
            }
            return string.toString();
        } else
            return null;

    }

    public static byte[] hexStringToBytes(String hexString) { // 16进制字符串转字节数组
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }

    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    /**
     * @Title:bytes2HexString
     * @Description:字节数组转16进制字符串
     * @param b 字节数组
     * @return 16进制字符串
     * @throws
     */
    public static String bytes2HexString(byte[] b) {
        StringBuffer result = new StringBuffer();
        String hex;
        for (int i = 0; i < b.length; i++) {
            hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            result.append(hex.toUpperCase() + " ");
        }
        return result.toString();
    }

    /**
     * @Title:byte2HexString
     * @Description:字节转16进制字符串
     * @param b 字节
     * @return 16进制字符串
     * @throws
     */
    public static String byte2HexString(byte b) {
        StringBuffer result = new StringBuffer();
        String hex;
        hex = Integer.toHexString(b & 0xFF);
        if (hex.length() == 1) {
            hex = '0' + hex;
        }
        result.append(hex.toUpperCase());
        return result.toString();
    }

    /**
     * char
     * 
     * @Title:hexString2Bytes
     * @Description:16进制字符串转字节数组
     * @param src 16进制字符串
     * @return 字节数组
     * @throws
     */
    public static byte[] hexString2Bytes(String src) {
        int l = src.length() / 2;
        byte[] ret = new byte[l];
        for (int i = 0; i < l; i++) {
            ret[i] = (byte) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
        }
        return ret;
    }

    /**
     * char
     * 
     * @Title:hexString2Bytes
     * @Description:16进制字符串转字符数组
     * @param src 16进制字符串
     * @return 字符数组
     * @throws
     */
    public static char[] hexString2Chars(String src) {
        int l = src.length() / 2;
        char[] ret = new char[l];
        for (int i = 0; i < l; i++) {
            ret[i] = (char) (Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue() & 0xFF);
        }
        return ret;
    }

    /**
     * @Title:string2HexString
     * @Description:字符串转16进制字符串
     * @param strPart 字符串
     * @return 16进制字符串
     * @throws
     */
    public static String string2HexString(String strPart) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < strPart.length(); i++) {
            int ch = (int) strPart.charAt(i);
            String strHex = Integer.toHexString(ch);
            hexString.append(strHex + " ");
        }
        return hexString.toString().substring(0, hexString.toString().length() - 1);
    }
    public static String string2HexStringw(String strPart) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < strPart.length(); i++) {
            int ch = (int) strPart.charAt(i);
            String strHex = Integer.toHexString(ch);
            hexString.append(strHex + "");
        }
        return hexString.toString().substring(0, hexString.toString().length());
    }
    /**
     * @Title:hexString2String
     * @Description:16进制字符串转字符串
     * @param src 16进制字符串
     * @return 字节数组
     * @throws
     */
    public static String hexString2String(String src) {
        String temp = "";
        for (int i = 0; i < src.length() / 2; i++) {
            temp = temp + (char) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
        }
        return temp;
    }

    /**
     * @Title:char2Byte
     * @Description:字符转成字节数据char-->integer-->byte
     * @param src
     * @return
     * @throws
     */
    public static Byte char2Byte(Character src) {
        return Integer.valueOf((int) src).byteValue();
    }

    /**
     * @Title:intToHexString
     * @Description:10进制数字转成16进制
     * @param a   转化数据
     * @param len 占用字节数
     * @return
     * @throws
     */
    public static String intToHexString(int a, int len) {
        len <<= 1;
        String hexString = Integer.toHexString(a);
        int b = len - hexString.length();
        if (b > 0) {
            for (int i = 0; i < b; i++) {
                hexString = "0" + hexString;
            }
        }
        return hexString;
    }

    public static float byte2float(byte[] bys) {
        try {
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bys);
            DataInputStream dataInputStream = new DataInputStream(byteArrayInputStream);
            float v = dataInputStream.readFloat();
            return v;
        } catch (Exception ex) {
            return 0;
        }
    }

    /**
     * IEEE754转换
     * 
     * @param src
     * @return
     */
    public static float IEEE754(String src) {
        int l = src.length() / 2;
        byte[] ret = new byte[l];
        for (int i = 0; i < l; i++) {
            ret[i] = (byte) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
        }
        try {
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(ret);
            DataInputStream dataInputStream = new DataInputStream(byteArrayInputStream);
            float v = dataInputStream.readFloat();
            return v;
        } catch (Exception ex) {
            return 0;
        }
    }

    public static int MAX(int[] arr) {
        return Arrays.stream(arr).max().getAsInt();
    }

    public static int MAX(List<Integer> arr) {
        Integer tmp = arr.get(0);
        for (int i = 1; i < arr.size(); i++) {
            if (arr.get(i) > tmp) {
                tmp = arr.get(i);
            }
        }
        return tmp;
    }

    public static float MAX(float a[]) {
        float max = a[0];
        for (int i = 0; i < a.length; i++) {
            if (a[i] > max) {
                max = a[i];
            }
        }
        return max;
    }

    public static float MIN(float a[]) {
        float min = a[0];
        for (int i = 0; i < a.length; i++) {
            if (a[i] < min) {
                min = a[i];
            }
        }
        return min;
    }

    public static boolean isLinux() {
        return System.getProperty("os.name").toLowerCase().contains("linux");
    }

    public static boolean isWindows() {
        return System.getProperty("os.name").toLowerCase().contains("windows");
    }

    /**
     * 字符串转换为Ascii(逗号分隔)
     * 
     * @param value
     * @return
     */
    public static String stringToAscii(String value) {
        StringBuffer sbu = new StringBuffer();
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (i != chars.length - 1) {
                sbu.append(String.format("%02X", (int) chars[i])).append(",");
            } else {
                sbu.append(String.format("%02X", (int) chars[i]));
            }
        }
        return sbu.toString();
    }

    /**
     * 字符串转换为Ascii(无逗号分隔)
     * 
     * @param value
     * @return
     */
    public static String stringToAsciiTrim(String value) {
        StringBuffer sbu = new StringBuffer();
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            sbu.append(String.format("%02X", (int) chars[i]));
        }
        return sbu.toString();
    }

    /**
     * Ascii转换为字符串
     * 
     * @param value
     * @return
     */
    public static String asciiToString(String value) {
        StringBuffer sbu = new StringBuffer();
        String[] chars = value.split(",");
        for (int i = 0; i < chars.length; i++) {
            sbu.append((char) Integer.parseInt(chars[i]));
        }
        return sbu.toString();
    }

    /**
     * 转化日期为标准格式日期字符串
     * 
     * @param value
     * @return
     * @throws ParseException
     */
    public static String tosdate(Date dt) throws ParseException {
        if (dt != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM ddHH:mm:ss 'GMT'XXX yyyy", Locale.US);
            SimpleDateFormat csdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (dt.toString().contains("CST")) {
                return sdf2.format(csdf.parse(dt.toString()));
            } else if (dt.toString().contains("GMT")) {
                return sdf2.format(sdf.parse(dt.toString()));
            } else {
                return "0001-01-01 00:00:00";
            }
        } else {
            return "0001-01-01 00:00:00";
        }
    }

    /**
     * 转化日期字符串为标准格式日期字符串
     * 
     * @param value
     * @return
     * @throws ParseException
     */
    public static String stosdate(String dt) throws ParseException {
        if (dt != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM ddHH:mm:ss 'GMT'XXX yyyy", Locale.US);
            SimpleDateFormat csdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (dt.contains("CST")) {
                return sdf2.format(csdf.parse(dt));
            } else if (dt.contains("GMT")) {
                return sdf2.format(sdf.parse(dt));
            } else {
                return "0001-01-01 00:00:00";
            }
        } else {
            return "0001-01-01 00:00:00";
        }
    }

    /**
     * 转化日期为标准格式日期
     * 
     * @param value
     * @return
     * @throws ParseException
     */
    public static Date todate(Date dt) throws ParseException {
        if (dt != null) {
            TimeZone defaultTimeZone = TimeZone.getDefault();
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeZone(defaultTimeZone);
            Date sourceDate = calendar.getTime();
            System.out.println(sourceDate.toString());
            SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM ddHH:mm:ss 'GMT'XXX yyyy", Locale.US);
            SimpleDateFormat csdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (dt.toString().contains("CST")) {
                return csdf.parse(dt.toString());
            } else if (dt.toString().contains("GMT")) {
                return sdf.parse(dt.toString());
            } else if (dt.toString().contains("CDT")) {
                return csdf.parse(dt.toString());
            } else {
                return sdf2.parse("0001-01-01 00:00:00");
            }
        } else {
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf2.parse("0001-01-01 00:00:00");
        }
    }

    /**
     * 转化报文日期格式为日期:例如230606093315
     * 
     * @param value
     * @return
     * @throws ParseException
     */
    public static Date tosdate(String dts) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        try {
            if (dts != null) {
                if (!dts.substring(0, 2).equals("20")) {
                    dts = "20" + dts;
                }
                return sdf.parse(dts);
            } else {
                return sdf.parse("00010101000000");
            }
        } catch (Exception e) {
            return new Date();
        }
    }

    /**
     * Integer判空置0
     * 
     * @param value
     * @return
     * @throws ParseException
     */
    public static Integer isnull(Integer value) {
        if (value == null)
            return 0;
        else
            return value;
    }

    /**
     * Stirng判空置""
     * 
     * @param value
     * @return
     * @throws ParseException
     */
    public static String isnull(String value) {
        if (value == null)
            return "";
        else
            return value;
    }

    /**
     * Stirng判空置""
     *
     * @param value
     * @return
     * @throws ParseException
     */
    public static String isnullToInteger(String value) {
        if (value == null)
            return "0";
        else
            return value;
    }

    /**
     * Long判空置0
     * 
     * @param value
     * @return
     * @throws ParseException
     */
    public static Long isnull(Long value) {
        if (value == null)
            return 0L;
        else
            return value;
    }

    /**
     * Float判空置0
     * 
     * @param value
     * @return
     * @throws ParseException
     */
    public static Float isnull(Float value) {
        if (value == null)
            return 0f;
        else
            return value;
    }

    /**
     * CRC-8
     * 
     * <table width="400px" border="1" cellpadding="0" cellspacing="0">
     * <tr>
     * <th>多项式</th>
     * <th>初始值</th>
     * <th>异或值</th>
     * <th>Bit反转</th>
     * </tr>
     * <tr>
     * <td align="center">0x07</td>
     * <td align="center">0x00</td>
     * <td align="center">0x00</td>
     * <td align="center">MSB First</td>
     * </tr>
     * </table>
     * 
     * @param source
     * @param offset
     * @param length
     * @return
     */
    public static int CRC8(byte[] source, int offset, int length) {
        int wCRCin = 0x00;
        int wCPoly = 0x07;
        for (int i = offset, cnt = offset + length; i < cnt; i++) {
            for (int j = 0; j < 8; j++) {
                boolean bit = ((source[i] >> (7 - j) & 1) == 1);
                boolean c07 = ((wCRCin >> 7 & 1) == 1);
                wCRCin <<= 1;
                if (c07 ^ bit)
                    wCRCin ^= wCPoly;
            }
        }
        wCRCin &= 0xFF;
        return wCRCin ^= 0x00;
    }

    /**
     * CRC-8/DARC
     * 
     * <table width="400px" border="1" cellpadding="0" cellspacing="0">
     * <tr>
     * <th>多项式</th>
     * <th>初始值</th>
     * <th>异或值</th>
     * <th>Bit反转</th>
     * </tr>
     * <tr>
     * <td align="center">0x39</td>
     * <td align="center">0x00</td>
     * <td align="center">0x00</td>
     * <td align="center">LSB First</td>
     * </tr>
     * </table>
     * 
     * @param source
     * @param offset
     * @param length
     * @return
     */
    public static int CRC8_DARC(byte[] source, int offset, int length) {
        int wCRCin = 0x00;
        // Integer.reverse(0x39) >>> 24
        int wCPoly = 0x9C;
        for (int i = offset, cnt = offset + length; i < cnt; i++) {
            wCRCin ^= ((long) source[i] & 0xFF);
            for (int j = 0; j < 8; j++) {
                if ((wCRCin & 0x01) != 0) {
                    wCRCin >>= 1;
                    wCRCin ^= wCPoly;
                } else {
                    wCRCin >>= 1;
                }
            }
        }
        return wCRCin ^= 0x00;
    }

    /**
     * CRC-8/ITU
     * 
     * <table width="400px" border="1" cellpadding="0" cellspacing="0">
     * <tr>
     * <th>多项式</th>
     * <th>初始值</th>
     * <th>异或值</th>
     * <th>Bit反转</th>
     * </tr>
     * <tr>
     * <td align="center">0x07</td>
     * <td align="center">0x00</td>
     * <td align="center">0x55</td>
     * <td align="center">MSB First</td>
     * </tr>
     * </table>
     * 
     * @param source
     * @param offset
     * @param length
     * @return
     */
    public static int CRC8_ITU(byte[] source, int offset, int length) {
        int wCRCin = 0x00;
        int wCPoly = 0x07;
        for (int i = offset, cnt = offset + length; i < cnt; i++) {
            for (int j = 0; j < 8; j++) {
                boolean bit = ((source[i] >> (7 - j) & 1) == 1);
                boolean c07 = ((wCRCin >> 7 & 1) == 1);
                wCRCin <<= 1;
                if (c07 ^ bit)
                    wCRCin ^= wCPoly;
            }
        }
        wCRCin &= 0xFF;
        return wCRCin ^= 0x55;
    }

    /**
     * CRC-8/MAXIM
     * 
     * <table width="400px" border="1" cellpadding="0" cellspacing="0">
     * <tr>
     * <th>多项式</th>
     * <th>初始值</th>
     * <th>异或值</th>
     * <th>Bit反转</th>
     * </tr>
     * <tr>
     * <td align="center">0x31</td>
     * <td align="center">0x00</td>
     * <td align="center">0x00</td>
     * <td align="center">LSB First</td>
     * </tr>
     * </table>
     * 
     * @param source
     * @param offset
     * @param length
     * @return
     */
    public static int CRC8_MAXIM(byte[] source, int offset, int length) {
        int wCRCin = 0x00;
        // Integer.reverse(0x31) >>> 24
        int wCPoly = 0x8C;
        for (int i = offset, cnt = offset + length; i < cnt; i++) {
            wCRCin ^= ((long) source[i] & 0xFF);
            // System.out.println(source[i]);
            for (int j = 0; j < 8; j++) {
                if ((wCRCin & 0x01) != 0) {
                    wCRCin >>= 1;
                    wCRCin ^= wCPoly;
                } else {
                    wCRCin >>= 1;
                }
            }
        }
        return wCRCin ^= 0x00;
    }

    /**
     * CRC-8/ROHC
     * 
     * <table width="400px" border="1" cellpadding="0" cellspacing="0">
     * <tr>
     * <th>多项式</th>
     * <th>初始值</th>
     * <th>异或值</th>
     * <th>Bit反转</th>
     * </tr>
     * <tr>
     * <td align="center">0x07</td>
     * <td align="center">0xFF</td>
     * <td align="center">0x00</td>
     * <td align="center">LSB First</td>
     * </tr>
     * </table>
     * 
     * @param source
     * @param offset
     * @param length
     * @return
     */
    public static int CRC8_ROHC(byte[] source, int offset, int length) {
        int wCRCin = 0xFF;
        // Integer.reverse(0x07) >>> 24
        int wCPoly = 0xE0;
        for (int i = offset, cnt = offset + length; i < cnt; i++) {
            wCRCin ^= ((long) source[i] & 0xFF);
            for (int j = 0; j < 8; j++) {
                if ((wCRCin & 0x01) != 0) {
                    wCRCin >>= 1;
                    wCRCin ^= wCPoly;
                } else {
                    wCRCin >>= 1;
                }
            }
        }
        return wCRCin ^= 0x00;
    }

    public static byte[] byteConcat(byte[] bt1, byte[] bt2) {
        byte[] bt4 = new byte[bt1.length + bt2.length];
        int len = 0;
        System.arraycopy(bt1, 0, bt4, 0, bt1.length);
        len += bt1.length;
        System.arraycopy(bt2, 0, bt4, len, bt2.length);
        return bt4;
    }

    public static float[] byteConcat(float[] bt1, float[] bt2) {
        float[] bt4 = new float[bt1.length + bt2.length];
        int len = 0;
        System.arraycopy(bt1, 0, bt4, 0, bt1.length);
        len += bt1.length;
        System.arraycopy(bt2, 0, bt4, len, bt2.length);
        return bt4;
    }

    public static boolean isNumeric(String str) {
        if (null == str || "".equals(str)) {
            return false;
        }
        String regx = "[+-]*\\d+\\.?\\d*[Ee]*[+-]*\\d+";
        Pattern pattern = Pattern.compile(regx);
        boolean isNumber = pattern.matcher(str).matches();
        if (isNumber) {
            return isNumber;
        }
        regx = "^[-\\+]?[.\\d]*$";
        pattern = Pattern.compile(regx);
        return pattern.matcher(str).matches();
    }
}
